/**
 * 设备指纹收集工具类
 * 用于收集用户设备信息，实现匿名用户识别
 */
import request from './request'

class DeviceFingerprint {
  constructor() {
    this.deviceInfo = null
    this.userToken = null
    this.userIdentity = null
  }

  /**
   * 收集设备信息
   * @returns {Object} 设备信息对象
   */
  async collectDeviceInfo() {
    try {
      console.log('🔍 开始收集设备信息...')
      
      // 获取基础设备信息
      const deviceInfo = {
        screenResolution: `${screen.width}x${screen.height}`,
        timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
        language: navigator.language || navigator.userLanguage,
        platform: navigator.platform,
        userAgent: navigator.userAgent,
        colorDepth: screen.colorDepth,
        pixelDepth: screen.pixelDepth,
        cookieEnabled: navigator.cookieEnabled,
        doNotTrack: navigator.doNotTrack,
        hardwareConcurrency: navigator.hardwareConcurrency || 'unknown'
      }

      // 获取Canvas指纹
      const canvasFingerprint = await this.getCanvasFingerprint()
      
      // 获取WebGL指纹
      const webglFingerprint = await this.getWebGLFingerprint()
      
      // 获取字体信息
      const fonts = await this.getAvailableFonts()
      
      // 组合所有信息生成设备指纹
      const fingerprintData = {
        ...deviceInfo,
        canvasFingerprint,
        webglFingerprint,
        fonts: fonts.slice(0, 20), // 只取前20个字体，避免数据过大
        timestamp: Date.now()
      }

      // 生成设备指纹哈希
      console.log('📊 设备信息收集完成，正在生成指纹...')
      const deviceFingerprint = await this.generateHash(JSON.stringify(fingerprintData))
      console.log('✅ 设备指纹生成成功:', deviceFingerprint.substring(0, 8) + '...')
      
      this.deviceInfo = {
        deviceFingerprint,
        screenResolution: deviceInfo.screenResolution,
        timezone: deviceInfo.timezone,
        language: deviceInfo.language,
        platform: deviceInfo.platform,
        userAgent: deviceInfo.userAgent
      }

      return this.deviceInfo
    } catch (error) {
      console.error('收集设备信息失败:', error)
      // 返回基础信息作为备选方案
      return {
        deviceFingerprint: await this.generateHash(navigator.userAgent + Date.now()),
        screenResolution: `${screen.width}x${screen.height}`,
        timezone: 'Asia/Shanghai',
        language: navigator.language || 'zh-CN',
        platform: navigator.platform || 'unknown',
        userAgent: navigator.userAgent
      }
    }
  }

  /**
   * 获取Canvas指纹
   * @returns {string} Canvas指纹
   */
  async getCanvasFingerprint() {
    try {
      const canvas = document.createElement('canvas')
      const ctx = canvas.getContext('2d')
      
      // 绘制文本和图形
      ctx.textBaseline = 'top'
      ctx.font = '14px Arial'
      ctx.fillStyle = '#f60'
      ctx.fillRect(125, 1, 62, 20)
      ctx.fillStyle = '#069'
      ctx.fillText('华南师范大学VR展馆 🏛️', 2, 15)
      ctx.fillStyle = 'rgba(102, 204, 0, 0.7)'
      ctx.fillText('设备指纹识别', 4, 45)

      return canvas.toDataURL()
    } catch (error) {
      console.error('获取Canvas指纹失败:', error)
      return 'canvas_not_supported'
    }
  }

  /**
   * 获取WebGL指纹
   * @returns {string} WebGL指纹
   */
  async getWebGLFingerprint() {
    try {
      const canvas = document.createElement('canvas')
      const gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl')
      
      if (!gl) {
        return 'webgl_not_supported'
      }

      const debugInfo = gl.getExtension('WEBGL_debug_renderer_info')
      const vendor = gl.getParameter(debugInfo?.UNMASKED_VENDOR_WEBGL || gl.VENDOR)
      const renderer = gl.getParameter(debugInfo?.UNMASKED_RENDERER_WEBGL || gl.RENDERER)
      
      return `${vendor}~${renderer}`
    } catch (error) {
      console.error('获取WebGL指纹失败:', error)
      return 'webgl_error'
    }
  }

  /**
   * 获取可用字体列表
   * @returns {Array} 字体列表
   */
  async getAvailableFonts() {
    const testFonts = [
      'Arial', 'Helvetica', 'Times New Roman', 'Courier New', 'Verdana',
      'Georgia', 'Palatino', 'Garamond', 'Bookman', 'Comic Sans MS',
      'Trebuchet MS', 'Arial Black', 'Impact', '微软雅黑', '宋体',
      '黑体', '楷体', '仿宋', 'SimSun', 'SimHei'
    ]
    
    const availableFonts = []
    
    // 创建测试用的span元素
    const testString = 'mmmmmmmmmmlli'
    const testSize = '72px'
    const baseFonts = ['monospace', 'sans-serif', 'serif']
    
    const span = document.createElement('span')
    span.style.fontSize = testSize
    span.style.position = 'absolute'
    span.style.left = '-9999px'
    span.textContent = testString
    document.body.appendChild(span)
    
    try {
      for (const font of testFonts) {
        let detected = false
        
        for (const baseFont of baseFonts) {
          span.style.fontFamily = `${font}, ${baseFont}`
          const width = span.offsetWidth
          const height = span.offsetHeight
          
          span.style.fontFamily = baseFont
          const baseWidth = span.offsetWidth
          const baseHeight = span.offsetHeight
          
          if (width !== baseWidth || height !== baseHeight) {
            detected = true
            break
          }
        }
        
        if (detected) {
          availableFonts.push(font)
        }
      }
    } finally {
      document.body.removeChild(span)
    }
    
    return availableFonts
  }

  /**
   * 生成哈希值
   * @param {string} text 要哈希的文本
   * @returns {string} SHA-256哈希值或备选哈希
   */
  async generateHash(text) {
    // 检查是否支持 Web Crypto API
    if (typeof crypto !== 'undefined' && crypto.subtle && crypto.subtle.digest) {
      try {
        const encoder = new TextEncoder()
        const data = encoder.encode(text)
        const hashBuffer = await crypto.subtle.digest('SHA-256', data)
        const hashArray = Array.from(new Uint8Array(hashBuffer))
        return hashArray.map(b => b.toString(16).padStart(2, '0')).join('')
      } catch (error) {
        console.warn('Web Crypto API 不可用，使用备选哈希方法:', error.message)
      }
    } else {
      console.warn('Web Crypto API 不支持，使用备选哈希方法')
    }
    
    // 备选哈希方法 - 使用多种简单哈希算法组合
    return this.fallbackHash(text)
  }

  /**
   * 备选哈希方法
   * @param {string} text 要哈希的文本
   * @returns {string} 备选哈希值
   */
  fallbackHash(text) {
    // 组合多种哈希算法提高唯一性
    let hash1 = 0
    let hash2 = 0
    let hash3 = 0
    
    for (let i = 0; i < text.length; i++) {
      const char = text.charCodeAt(i)
      
      // 第一种哈希
      hash1 = ((hash1 << 5) - hash1) + char
      hash1 = hash1 & hash1 // 转换为32位整数
      
      // 第二种哈希
      hash2 = ((hash2 << 3) + hash2) + char
      hash2 = hash2 & hash2
      
      // 第三种哈希
      hash3 = ((hash3 * 31) + char) % 982451653
    }
    
    // 组合三个哈希值
    const combined = Math.abs(hash1).toString(16) + 
                    Math.abs(hash2).toString(16) + 
                    Math.abs(hash3).toString(16)
    
    // 截取固定长度并补充时间戳确保唯一性
    const timestamp = Date.now().toString(16)
    return (combined + timestamp).substring(0, 32)
  }

  /**
   * 向后端发送设备识别请求
   * @returns {Object} 用户身份信息
   */
  async identifyUser() {
    try {
      // 如果还没有收集设备信息，先收集
      if (!this.deviceInfo) {
        await this.collectDeviceInfo()
      }

      console.log('📤 发送设备识别请求:', {
        deviceFingerprint: this.deviceInfo.deviceFingerprint.substring(0, 8) + '...',
        screenResolution: this.deviceInfo.screenResolution,
        timezone: this.deviceInfo.timezone,
        language: this.deviceInfo.language,
        platform: this.deviceInfo.platform
      })

      // 调用后端API进行设备识别
      const response = await request.post('/anonymousUsers/identify', this.deviceInfo)
      
      console.log('设备识别响应:', response)

      // 检查响应格式 - 适配不同的后端响应结构
      let responseData = null
      
      if (response.data && response.data.data) {
        // 格式1: { status: 200, data: { userToken: "...", ... } }
        responseData = response.data.data
      } else if (response.data && response.data.userToken) {
        // 格式2: { userToken: "...", ... }
        responseData = response.data
      } else if (response.userToken) {
        // 格式3: 直接返回用户数据
        responseData = response
      } else {
        console.warn('未识别的响应格式:', response)
        throw new Error('设备识别响应格式不正确')
      }

      // 检查响应状态和数据
      if (responseData && responseData.userToken) {
        this.userIdentity = responseData
        this.userToken = responseData.userToken
        
        // 将用户Token存储到localStorage
        localStorage.setItem('userToken', this.userToken)
        localStorage.setItem('userIdentity', JSON.stringify(this.userIdentity))
        
        console.log('用户识别成功:', {
          userToken: this.userToken,
          isNewUser: this.userIdentity.isNewUser,
          visitCount: this.userIdentity.visitCount,
          bookingCount: this.userIdentity.bookingCount
        })

        return this.userIdentity
      } else {
        throw new Error(`设备识别响应数据不完整: ${JSON.stringify(responseData)}`)
      }
    } catch (error) {
      console.error('设备识别失败:', error)
      
      // 生成临时的本地标识
      const tempToken = 'TEMP_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9)
      localStorage.setItem('userToken', tempToken)
      
      // 创建临时用户身份
      const tempIdentity = {
        userToken: tempToken,
        isNewUser: true,
        visitCount: 1,
        bookingCount: 0,
        isTemporary: true,
        error: error.message,
        timestamp: new Date().toISOString()
      }
      
      // 存储临时身份信息
      this.userIdentity = tempIdentity
      this.userToken = tempToken
      localStorage.setItem('userIdentity', JSON.stringify(tempIdentity))
      
      console.warn('已生成临时用户身份:', tempIdentity)
      
      return tempIdentity
    }
  }

  /**
   * 获取当前用户Token
   * @returns {string} 用户Token
   */
  getUserToken() {
    return this.userToken || localStorage.getItem('userToken')
  }

  /**
   * 获取用户身份信息
   * @returns {Object} 用户身份信息
   */
  getUserIdentity() {
    if (this.userIdentity) {
      return this.userIdentity
    }
    
    const stored = localStorage.getItem('userIdentity')
    if (stored) {
      try {
        return JSON.parse(stored)
      } catch (error) {
        console.error('解析存储的用户身份信息失败:', error)
      }
    }
    
    return null
  }

  /**
   * 清除用户信息（用于测试）
   */
  clearUserInfo() {
    this.userToken = null
    this.userIdentity = null
    localStorage.removeItem('userToken')
    localStorage.removeItem('userIdentity')
  }

  /**
   * 初始化用户识别（应用启动时调用）
   * @returns {Object} 用户身份信息
   */
  async initialize() {
    try {
      // 检查是否已有存储的用户信息
      const existingToken = localStorage.getItem('userToken')
      if (existingToken && !existingToken.startsWith('TEMP_')) {
        console.log('发现已存在的用户Token:', existingToken)
        this.userToken = existingToken
        
        const storedIdentity = localStorage.getItem('userIdentity')
        if (storedIdentity) {
          try {
            this.userIdentity = JSON.parse(storedIdentity)
            console.log('使用存储的用户身份信息:', this.userIdentity)
            return this.userIdentity
          } catch (error) {
            console.error('解析存储的用户身份信息失败，重新识别用户')
          }
        }
      }

      // 执行设备识别
      console.log('开始设备识别流程...')
      return await this.identifyUser()
    } catch (error) {
      console.error('用户识别初始化失败:', error)
      return null
    }
  }
}

// 创建单例实例
const deviceFingerprint = new DeviceFingerprint()

export default deviceFingerprint